//
//  ViewController.m
//  下载大文件
//
//  Created by 胡先剑 on 16/3/31.
//  Copyright © 2016年 胡先剑. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<NSURLConnectionDataDelegate>
{
    NSMutableData *mData;
    unsigned long long allLength;
    NSFileHandle *fh;
    
    BOOL bDownLoading;
    NSURLConnection *con;
    unsigned long long curLength;
}

@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}


- (IBAction)btnPressed:(id)sender
{
    [self downloadBigFile2];
}

//#pragma mark - 下载大文件(边下载边保存，不会有内存问题)
//- (void)downloadBigFile1
//{
//    NSString *urlStr = [NSString stringWithFormat:@"http://localhost:8080/MJServer/resources/videos.zip"];
//    NSURL *url = [NSURL URLWithString:urlStr];
//    NSURLRequest *request = [NSURLRequest requestWithURL:url];
//    
//    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//    [con start];
//    
//}
//
///* 接收到服务器响应 */
//- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
//{
//    NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
//    allLength = [r.allHeaderFields[@"Content-Length"] intValue];
//    mData = [NSMutableData data];
//    self.progressView.progress = 0.0f;
//    
//    /* 创建文件 */
//    NSFileManager *fm = [NSFileManager defaultManager];
//    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
//    NSString *filePath = [path stringByAppendingPathComponent:connection.currentRequest.URL.lastPathComponent];/* 保存的路径 */
//    [fm createFileAtPath:filePath contents:nil attributes:nil];
//    fh = [NSFileHandle fileHandleForWritingAtPath:filePath];
//}
//
///* 接收到服务器返回的数据,(这个方法会多次运行，因为数据会被分割成若干块发送,块的大小不是固定的) */
//- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
//{
//    [fh writeData:data];
//    
//    NSLog(@"接受数据:%llu%%",fh.offsetInFile*100/allLength);
//    self.progressView.progress = (float)fh.offsetInFile/allLength;
//}
//
///* 接收完成 */
//- (void)connectionDidFinishLoading:(NSURLConnection *)connection
//{
// 
//    [fh closeFile];
//}


#pragma mark - 下载大文件(断点续传)
- (void)downloadBigFile2
{
    if (bDownLoading) // 是否在下载
    {
        /* 如果在正在下载,停止 */
        [con cancel];
        /* 关闭文件指针 */
        [fh closeFile];
        
        bDownLoading = NO;
    }
    else
    {
        NSString *urlStr = [NSString stringWithFormat:@"http://localhost:8080/MJServer/resources/videos.zip"];
        NSURL *url = [NSURL URLWithString:urlStr];
        /* 创建临时文件 */
        NSString *tmpFilePath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/%@.tmp",url.lastPathComponent];
        
        NSFileManager *fm = [NSFileManager defaultManager];
        if (![fm fileExistsAtPath:tmpFilePath])
        {
            /* 1. 文件不存在,新下载 */
            /* 创建文件 */
            [fm createFileAtPath:tmpFilePath contents:nil attributes:nil];
            /* 创建文件读写指针 */
            fh = [NSFileHandle fileHandleForWritingAtPath:tmpFilePath];
            
            curLength = 0;
            
        }
        else
        {
            /* 2. 文件存在就续传 */
            /* 打开文件 */
            fh = [NSFileHandle fileHandleForWritingAtPath:tmpFilePath];
            /* 指针 */
            curLength = [fh seekToEndOfFile];
        }
        
        /* 设置请求头, 告诉服务器断点续传的位置 */
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        /* bytes=当前长度值— (指请求从指定长度之后的数据) */
        NSString *rangStr = [NSString stringWithFormat:@"bytes=%lld-",curLength];
        [request setValue:rangStr forHTTPHeaderField:@"Range"];
        allLength = [self getFileLengthWithURL:url];
        
        con = [[NSURLConnection alloc] initWithRequest:request delegate:self];
        [con start];
        bDownLoading = YES;
    }
}

/* 连接错误 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"连接错误:%@",[error localizedDescription]);
    bDownLoading = NO;
}

/* 接收到服务器响应 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
    NSLog(@"当前长度:%lld,待接收长度:%lld",curLength,[r.allHeaderFields[@"Content-Length"] longLongValue]);
    self.progressView.progress = (float)curLength/allLength;
}

/* 接收到服务器返回的数据,(这个方法会多次运行，因为数据会被分割成若干块发送,块的大小不是固定的) */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [fh writeData:data];
    NSLog(@"接受数据:%llu%%",fh.offsetInFile*100/allLength);
    self.progressView.progress = (float)fh.offsetInFile/allLength;
}

/* 接收完成 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{

    [fh closeFile];
    bDownLoading = NO;
    
    /* 移动到Documents 下 */
    NSURL *url = con.currentRequest.URL;
    NSString *tmpFilePath = [NSHomeDirectory() stringByAppendingFormat:@"/tmp/%@.tmp",url.lastPathComponent];
    NSString *docFilePath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@",url.lastPathComponent];
    NSFileManager *fm = [NSFileManager defaultManager];
    [fm moveItemAtPath:tmpFilePath toPath:docFilePath error:nil];
}


- (unsigned long long)getFileLengthWithURL:(NSURL *)url
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"HEAD"; // GET POST
    // HEAD方式下:服务器只返回响应头,不返回响应体
    NSURLResponse *response;
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    return response.expectedContentLength;// 长度
}
@end
